<datatable-demos></datatable-demos>

<div class="content-section introduction">
    <div>
        <span class="feature-title">DataTable</span>
        <span>DataTable displays data in tabular format.</span>
    </div>
</div>

<div class="content-section implementation">
    <h3 class="first">Basic</h3>
    <p-dataTable [value]="cars" [loading]="loading">
        <p-column field="vin" header="Vin"></p-column>
        <p-column field="year" header="Year"></p-column>
        <p-column field="brand" header="Brand"></p-column>
        <p-column field="color" header="Color"></p-column>
    </p-dataTable>
    
    <h3>Dynamic Columns</h3>
    <p-dataTable [value]="cars" [loading]="loading">
        <p-column *ngFor="let col of cols" [field]="col.field" [header]="col.header"></p-column>
    </p-dataTable>
</div>

<div class="content-section documentation">
    <p-tabView effect="fade">
        <p-tabPanel header="Documentation">
            <h3>Import</h3>
<pre>
<code class="language-typescript" pCode ngNonBindable>
import &#123;DataTableModule,SharedModule&#125; from 'primeng/primeng';
</code>
</pre>

            <h3>Getting Started</h3>
            <p>DataTable requires a value as an array of objects and columns defined with p-column component. Throughout the samples, a car interface having
            vin, brand, year and color properties is used to define an object to be displayed by the datatable. Cars are loaded by a CarService that
            connects to a server to fetch the cars with a Promise.
            </p>
<pre>
<code class="language-typescript" pCode ngNonBindable>
export interface Car &#123;
    vin;
    year;
    brand;
    color;
&#125;
</code>
</pre>

<pre>
<code class="language-typescript" pCode ngNonBindable>
import &#123;Injectable&#125; from 'angular2/core';
import &#123;Http, Response&#125; from 'angular2/http';
import &#123;Car&#125; from '../domain/car';
    
@Injectable()
export class CarService &#123;
    
    constructor(private http: Http) &#123;&#125;

    getCarsSmall() &#123;
        return this.http.get('/showcase/resources/data/cars-small.json')
                    .toPromise()
                    .then(res => &lt;Car[]&gt; res.json().data)
                    .then(data => &#123; return data; &#125;);
    &#125;
&#125;
</code>
</pre>
            <p>Following sample datatable has 4 columns and retrieves the data from a service on init.</p>

<pre>
<code class="language-typescript" pCode ngNonBindable>
export class DataTableDemo implements OnInit &#123;

    cars: Car[];

    constructor(private carService: CarService) &#123; &#125;

    ngOnInit() &#123;
        this.carService.getCarsSmall().then(cars => this.cars = cars);
    &#125;
&#125;
</code>
</pre>

        <p>List of cars are bound to the value property and columns are defined using p-column component.</p>
<pre>
<code class="language-markup" pCode ngNonBindable>
&lt;p-dataTable [value]="cars"&gt;
    &lt;p-column field="vin" header="Vin"&gt;&lt;/p-column&gt;
    &lt;p-column field="year" header="Year"&gt;&lt;/p-column&gt;
    &lt;p-column field="brand" header="Brand"&gt;&lt;/p-column&gt;
    &lt;p-column field="color" header="Color"&gt;&lt;/p-column&gt;
&lt;/p-dataTable&gt;
</code>
</pre>

            <h3>Column Component</h3>
            <p>Column component defines various options to specify corresponding features.</p>
            <h3>Properties</h3>
            <div class="doc-tablewrapper">
                <table class="doc-table">
                    <thead>
                        <tr>
                            <th>Name</th>
                            <th>Type</th>
                            <th>Default</th>
                            <th>Description</th>
                        </tr>
                    </thead>
                    <tbody>
                        <tr>
                            <td>field</td>
                            <td>string</td>
                            <td>null</td>
                            <td>Property of a row data.</td>
                        </tr>
                        <tr>
                            <td>sortField</td>
                            <td>string</td>
                            <td>null</td>
                            <td>Property of a row data used for sorting, defaults to field.</td>
                        </tr>
                        <tr>
                            <td>header</td>
                            <td>string</td>
                            <td>null</td>
                            <td>Header text of a column.</td>
                        </tr>
                        <tr>
                            <td>footer</td>
                            <td>string</td>
                            <td>null</td>
                            <td>Footer text of a column.</td>
                        </tr>
                        <tr>
                            <td>sortable</td>
                            <td>any</td>
                            <td>false</td>
                            <td>Defines if a column is sortable.</td>
                        </tr>
                        <tr>
                            <td>sortFunction</td>
                            <td>function</td>
                            <td>null</td>
                            <td>Sort function for custom sorting.</td>
                        </tr>
                        <tr>
                            <td>editable</td>
                            <td>boolean</td>
                            <td>false</td>
                            <td>Defines if a column is editable.</td>
                        </tr>
                        <tr>
                            <td>filter</td>
                            <td>boolean</td>
                            <td>false</td>
                            <td>Defines if a column can be filtered.</td>
                        </tr>
                        <tr>
                            <td>filterMatchMode</td>
                            <td>string</td>
                            <td>null</td>
                            <td>Defines filterMatchMode; "startsWith", "contains", "endsWidth", "equals", "notEquals" and "in".</td>
                        </tr>
                        <tr>
                            <td>filterType</td>
                            <td>string</td>
                            <td>text</td>
                            <td>Type of the filter input field.</td>
                        </tr>
                        <tr>
                            <td>filterPlaceholder</td>
                            <td>string</td>
                            <td>null</td>
                            <td>Defines placeholder of the input fields.</td>
                        </tr>
                        <tr>
                            <td>filterMaxlength</td>
                            <td>number</td>
                            <td>null</td>
                            <td>Specifies the maximum number of characters allowed in the filter element.</td>
                        </tr>
                        <tr>
                            <td>rowspan</td>
                            <td>string</td>
                            <td>null</td>
                            <td>Number of rows to span for grouping.</td>
                        </tr>
                        <tr>
                            <td>colspan</td>
                            <td>string</td>
                            <td>null</td>
                            <td>Number of columns to span for grouping.</td>
                        </tr>
                        <tr>
                            <td>style</td>
                            <td>object</td>
                            <td>null</td>
                            <td>Inline style of the column.</td>
                        </tr>
                        <tr>
                            <td>styleClass</td>
                            <td>string</td>
                            <td>null</td>
                            <td>Style class of the column.</td>
                        </tr>
                        <tr>
                            <td>tableStyle</td>
                            <td>string</td>
                            <td>null</td>
                            <td>Inline style of the table element.</td>
                        </tr>
                        <tr>
                            <td>tableStyleClass</td>
                            <td>string</td>
                            <td>null</td>
                            <td>Style class of the table element.</td>
                        </tr>
                        <tr>
                            <td>hidden</td>
                            <td>boolean</td>
                            <td>false</td>
                            <td>Controls visiblity of the column.</td>
                        </tr>
                        <tr>
                            <td>expander</td>
                            <td>boolean</td>
                            <td>false</td>
                            <td>Displays an icon to toggle row expansion.</td>
                        </tr>
                        <tr>
                            <td>selectionMode</td>
                            <td>string</td>
                            <td>null</td>
                            <td>Defines column based selection mode, options are "single" and "multiple".</td>
                        </tr>
                        <tr>
                            <td>frozen</td>
                            <td>boolean</td>
                            <td>false</td>
                            <td>Whether the column is fixed in horizontal scrolling or not.</td>
                        </tr>
                    </tbody>
                </table>
            </div>

<pre>
<code class="language-markup" pCode ngNonBindable>
&lt;p-column field="vin" header="Vin" [sortable]="true"&gt;&lt;/p-column&gt;
</code>
</pre>

            <h3>Dynamic Colums</h3>
            <p>Columns can be instantiated using an array as well by iterating with ngFor.</p>
<pre>
<code class="language-typescript" pCode ngNonBindable>
export class DataTableDemo implements OnInit &#123;

    cars: Car[];
    
    cols: any[];

    constructor(private carService: CarService) &#123; &#125;

    ngOnInit() &#123;
        this.carService.getCarsSmall().then(cars => this.cars = cars);
        
        this.cols = [
            &#123;field: 'vin', header: 'Vin'&#125;,
            &#123;field: 'year', header: 'Year'&#125;,
            &#123;field: 'brand', header: 'Brand'&#125;,
            &#123;field: 'color', header: 'Color'&#125;
        ];
    &#125;
&#125;
</code>
</pre>

<pre>
<code class="language-markup" pCode ngNonBindable>
&lt;p-dataTable [value]="cars"&gt;
    &lt;p-column *ngFor="let col of cols" [field]="col.field" [header]="col.header"&gt;&lt;/p-column&gt;
&lt;/p-dataTable&gt;
</code>
</pre>

            <h3>Managing Data</h3>
            <p>DataTable uses setter based checking to realize if the underlying data has changed to update the UI so your data changes such as adding or removing a record 
                should always create a new array reference instead of manipulating an existing array. For example, use slice instead of splice when removing an item 
                or use spread operator instead of push method when adding an item.</p>

            <h3>Templates</h3>
            <p>Field data of a corresponding row is displayed as the cell content by default, this can be customized using templating where the implicit variable passed to the ng-template 
                is the column definition and data of current row is the rowData property. In addition index of the current can be accessed using the optional rowIndex variable. 
                Similarly, custom content can be placed at the header and footer of a column with templating.</p>
            
            <p>A ng-template inside a column must be decorated with pTemplate directive along with the type to indicate where the ng-template belongs to. Possible values 
            are "header", "body" and "footer".</p>
<pre>
<code class="language-markup" pCode ngNonBindable>
&lt;p-column field="color" header="Color"&gt;
    &lt;ng-template let-col let-car="rowData" let-ri="rowIndex" pTemplate="body"&gt;
        &lt;span&gt;{{car[col.field]}}&lt;/span&gt;
    &lt;/ng-template&gt;
&lt;/p-column&gt;
&lt;p-column&gt;
    &lt;ng-template pTemplate="header"&gt;
        &lt;button type="button" pButton (click)="selectAllCars()" icon="fa-check"&gt;&lt;/button&gt;
    &lt;/ng-template&gt;
    &lt;ng-template let-car="rowData" pTemplate="body"&gt;
        &lt;button type="button" pButton (click)="selectCar(car)" icon="fa-search"&gt;&lt;/button&gt;
    &lt;/ng-template&gt;
&lt;/p-column&gt;
</code>
</pre>

            <p>Index of the row is available at the ng-template.</p>
<pre>
<code class="language-markup" pCode ngNonBindable>
    &lt;p-column&gt;
        &lt;ng-template let-car="rowData" let-i="rowIndex" pTemplate="body"&gt;
            &lt;button type="button" pButton (click)="selectCar(i)" icon="fa-search"&gt;&lt;/button&gt;
        &lt;/ng-template&gt;
    &lt;/p-column&gt;
</code>
</pre>

            <p>See the <a [routerLink]="['/datatable/templating']">live example.</a></p>

            <h3>Facets</h3>
            <p>Header and Footer are the two sections aka facets that are capable of displaying custom content.</p>
<pre>
<code class="language-typescript" pCode ngNonBindable>
import &#123;Header&#125; from 'primeng/primeng';
import &#123;Footer&#125; from 'primeng/primeng';
</code>
</pre>
<pre>
<code class="language-markup" pCode ngNonBindable>
&lt;p-dataTable [value]="cars"&gt;
    &lt;p-header&gt;List of Cars&lt;/p-header&gt;
    &lt;p-footer&gt;Choose from the list.&lt;/p-footer&gt;
    &lt;p-column field="vin" header="Vin"&gt;&lt;/p-column&gt;
    &lt;p-column field="year" header="Year"&gt;&lt;/p-column&gt;
    &lt;p-column field="brand" header="Brand"&gt;&lt;/p-column&gt;
    &lt;p-column field="color" header="Color"&gt;&lt;/p-column&gt;
&lt;/p-dataTable&gt;
</code>
</pre>
            <p>See the <a [routerLink]="['/datatable/facets']">live example.</a></p>

            <h3>Column Grouping</h3>
            <p>Columns can be grouped at header and footer using headerColumnGroup and footerColumnGroup components containing rows with
                columns. Templating is also supported inside grouped columns.</p>
<pre>
<code class="language-markup" pCode ngNonBindable>
&lt;p-dataTable [value]="sales"&gt;
    &lt;p-headerColumnGroup&gt;
        &lt;p-row&gt;
            &lt;p-column header="Brand" rowspan="3"&gt;&lt;/p-column&gt;
            &lt;p-column header="Sale Rate" colspan="4"&gt;&lt;/p-column&gt;
        &lt;/p-row&gt;
        &lt;p-row&gt;
            &lt;p-column header="Sales" colspan="2"&gt;&lt;/p-column&gt;
            &lt;p-column header="Profits" colspan="2"&gt;&lt;/p-column&gt;
        &lt;/p-row&gt;
        &lt;p-row&gt;
            &lt;p-column header="Last Year"&gt;&lt;/p-column&gt;
            &lt;p-column header="This Year"&gt;&lt;/p-column&gt;
            &lt;p-column header="Last Year"&gt;&lt;/p-column&gt;
            &lt;p-column header="This Year"&gt;&lt;/p-column&gt;
        &lt;/p-row&gt;
    &lt;/p-headerColumnGroup&gt;
    
    &lt;p-column field="brand"&gt;&lt;/p-column&gt;
    &lt;p-column field="lastYearSale"&gt;&lt;/p-column&gt;
    &lt;p-column field="thisYearSale"&gt;&lt;/p-column&gt;
    &lt;p-column field="lastYearProfit"&gt;&lt;/p-column&gt;
    &lt;p-column field="thisYearProfit"&gt;&lt;/p-column&gt;
    
    &lt;p-footerColumnGroup&gt;
        &lt;p-row&gt;
            &lt;p-column footer="Totals:" colspan="3"&gt;&lt;/p-column&gt;
            &lt;p-column footer="$506,202"&gt;&lt;/p-column&gt;
            &lt;p-column footer="$531,020"&gt;&lt;/p-column&gt;
        &lt;/p-row&gt;
    &lt;/p-footerColumnGroup&gt;
&lt;/p-dataTable&gt;
</code>
</pre>
            <p>See the <a [routerLink]="['/datatable/colgroup']">live example.</a></p>
            
            <h3>Row Grouping</h3>
            <p>Rows can either be grouped by a separate grouping row or using rowspan. In both cases, data has to be sorted by the grouping field initially.</p>
<pre>
<code class="language-markup" pCode ngNonBindable>
&lt;p-dataTable [value]="cars1" sortField="brand" rowGroupMode="subheader" groupField="brand"&gt;
    &lt;p-header&gt;Subheader&lt;/p-header&gt;
    &lt;ng-template pTemplate="rowgroupheader" let-rowData&gt;&#123;&#123;rowData['brand']&#125;&#125;&lt;/ng-template&gt;
    &lt;p-column field="color" header="Color"&gt;&lt;/p-column&gt;
    &lt;p-column field="year" header="Year"&gt;&lt;/p-column&gt;
    &lt;p-column field="vin" header="Vin"&gt;&lt;/p-column&gt;
&lt;/p-dataTable&gt;

&lt;p-dataTable [value]="cars2" sortField="brand" rowGroupMode="rowspan"&gt;
    &lt;p-header&gt;RowSpan&lt;/p-header&gt;
    &lt;p-column field="brand" header="Brand"&gt;&lt;/p-column&gt;
    &lt;p-column field="color" header="Color"&gt;&lt;/p-column&gt;
    &lt;p-column field="year" header="Year"&gt;&lt;/p-column&gt;
    &lt;p-column field="vin" header="Vin"&gt;&lt;/p-column&gt;
&lt;/p-dataTable&gt;
</code>
</pre>

            <p>Visibility of a group can be toggled using an icon placed next to the group name using expandableRowGroups property.
            By default all groups are collapsed and expandadRowGroups property needs to be populated with the group field values
            to show particular groups as expanded by default.</p>
<pre>
<code class="language-markup" pCode ngNonBindable>
&lt;p-dataTable [value]="cars" sortField="brand" rowGroupMode="subheader" groupField="brand" expandableRowGroups="true"&gt;
    &lt;p-header&gt;Subheader&lt;/p-header&gt;
    &lt;ng-template pTemplate="rowgroup" let-rowData&gt;&#123;&#123;rowData['brand']&#125;&#125;&lt;/ng-template&gt;
    &lt;p-column field="color" header="Color"&gt;&lt;/p-column&gt;
    &lt;p-column field="year" header="Year"&gt;&lt;/p-column&gt;
    &lt;p-column field="vin" header="Vin"&gt;&lt;/p-column&gt;
&lt;/p-dataTable&gt;
</code>
</pre>       

            <p>A footer for a row can be defined using the rowgroupfooter ng-template.</p> 
<pre>
<code class="language-markup" pCode ngNonBindable>
&lt;p-dataTable [value]="cars" sortField="brand" rowGroupMode="subheader" groupField="brand" expandableRowGroups="true"
        [sortableRowGroup]="false"&gt;
    &lt;p-header&gt;Toggleable Row Groups with Footers&lt;/p-header&gt;
    &lt;ng-template pTemplate="rowgroupheader" let-rowData&gt;&#123;&#123;rowData['brand']&#125;&#125;&lt;/ng-template&gt;
    &lt;p-column field="color" header="Color"&gt;&lt;/p-column&gt;
    &lt;p-column field="year" header="Year"&gt;&lt;/p-column&gt;
    &lt;p-column field="vin" header="Vin"&gt;&lt;/p-column&gt;
    &lt;p-column field="price" header="Price"&gt;
        &lt;ng-template let-col let-car="rowData" pTemplate="body"&gt;
            &lt;span&gt;&#123;&#123;car[col.field] | currency:'USD':true:'.0-0'&#125;&#125;&lt;/span&gt;
        &lt;/ng-template&gt;
    &lt;/p-column&gt;
    &lt;ng-template pTemplate="rowgroupfooter" let-car&gt;
        &lt;td colspan="3" style="text-align:right"&gt;Total Price&lt;/td&gt;
        &lt;td&gt;&#123;&#123;calculateGroupTotal(car['brand']) | currency:'USD':true:'.0-0' &#125;&#125;&lt;/td&gt;
    &lt;/ng-template&gt;
&lt;/p-dataTable&gt;
</code>
</pre>    

            <p>Clicking a row group sorts the data according to the group field, you can control this behavior using sortableRowGroup property.</p> 
    
            <p>See the <a [routerLink]="['/datatable/rowgroup']">live example.</a></p>

            <h3>Paginator</h3>
            <p>Pagination is enabled by setting paginator property to true, rows attribute defines the number of rows per page and pageLinks specify the the number
                of page links to display. See <a [routerLink]="['/paginator']">paginator</a> component for more information.</p>
<pre>
<code class="language-markup" pCode ngNonBindable>
&lt;p-dataTable [value]="cars" [rows]="10" [paginator]="true"&gt;
    &lt;p-column field="vin" header="Vin"&gt;&lt;/p-column&gt;
    &lt;p-column field="year" header="Year"&gt;&lt;/p-column&gt;
    &lt;p-column field="brand" header="Brand"&gt;&lt;/p-column&gt;
    &lt;p-column field="color" header="Color"&gt;&lt;/p-column&gt;
&lt;/p-dataTable&gt;
</code>
</pre>

            <p>Paginator can also be controlled via model using a binding to the first property where changes trigger a pagination. Optionaly this property supports 
            two-way binding so that model value can be updated on pagination as well. Here is an example to reset the paginator externally.</p>
<pre>
<code class="language-markup" pCode ngNonBindable>
&lt;p-dataTable [value]="cars" [rows]="10" [paginator]="true" [(first)]="first"&gt;
    &lt;p-column field="vin" header="Vin"&gt;&lt;/p-column&gt;
    &lt;p-column field="year" header="Year"&gt;&lt;/p-column&gt;
    &lt;p-column field="brand" header="Brand"&gt;&lt;/p-column&gt;
    &lt;p-column field="color" header="Color"&gt;&lt;/p-column&gt;
&lt;/p-dataTable&gt;

&lt;button type="button" (click)="reset()" label="Reset"&gt;&lt;/button&gt;
</code>
</pre>   

<pre>
<code class="language-typescript" pCode ngNonBindable>
export class DataTableDemo implements OnInit &#123;

    cars: Car[];
    
    first: number = 0;

    constructor(private carService: CarService) &#123; &#125;

    ngOnInit() &#123;
        this.carService.getCarsSmall().then(cars => this.cars = cars);
    &#125;
    
    reset() &#123;
        this.first = 0;
    &#125;
&#125;
</code>
</pre> 
            
            
            <p>See the <a [routerLink]="['/datatable/paginator']">live example.</a></p>

            <h3>Sorting</h3>
            <p>Simply enabling sortable property at column object is enough to make a column sortable. The property to use when 
            sorting is field by default and this can be customized using sortField.</p>
<pre>
<code class="language-markup" pCode ngNonBindable>
&lt;p-column field="vin" header="Vin" sortable="true"&gt;&lt;/p-column&gt;
</code>
</pre>
            <p>By default sorting is executed on the clicked column. To do multiple field sorting, set sortMode property to "multiple" and use metakey 
            when clicking on another column.</p>
<pre>
<code class="language-markup" pCode ngNonBindable>
&lt;p-dataTable [value]="cars" [sortMode]="multiple"&gt;
</code>
</pre>

            <p>In case you'd like to display the table as sorted by default initially on load, use the sortField-sortOrder properties in single mode.</p>
<pre>
<code class="language-markup" pCode ngNonBindable>
&lt;p-dataTable [value]="cars" sortField="year" [sortOrder]="1"&gt;
    &lt;p-column field="vin" header="Vin" sortable="true"&gt;&lt;/p-column&gt;
    &lt;p-column field="year" header="Year" sortable="true"&gt;&lt;/p-column&gt;
    &lt;p-column field="brand" header="Brand" sortable="true"&gt;&lt;/p-column&gt;
    &lt;p-column field="color" header="Color" sortable="true"&gt;&lt;/p-column&gt;
&lt;/p-dataTable&gt;
</code>
</pre>
            <p>In multiple mode, use the multiSortMeta property and bind an array of SortMeta objects.</p>
<pre>
<code class="language-markup" pCode ngNonBindable>
&lt;p-dataTable [value]="cars" [multiSortMeta]="multiSortMeta"&gt;
    &lt;p-column field="vin" header="Vin" sortable="true"&gt;&lt;/p-column&gt;
    &lt;p-column field="year" header="Year" sortable="true"&gt;&lt;/p-column&gt;
    &lt;p-column field="brand" header="Brand" sortable="true"&gt;&lt;/p-column&gt;
    &lt;p-column field="color" header="Color" sortable="true"&gt;&lt;/p-column&gt;
&lt;/p-dataTable&gt;
</code>
</pre>

<pre>
<code class="language-typescript" pCode ngNonBindable>
this.multiSortMeta = [];
this.multiSortMeta.push(&#123;field: 'year', order: 1&#125;);
this.multiSortMeta.push(&#123;field: 'brand', order: -1&#125;);
</code>
</pre>        

            <p>To customize sorting, set sortable option to <i>custom</i> and define a sortFunction that sorts the list.</p>
<pre>
<code class="language-markup" pCode ngNonBindable>
&lt;p-dataTable [value]="cars" [multiSortMeta]="multiSortMeta"&gt;
    &lt;p-column field="vin" header="Vin" sortable="true"&gt;&lt;/p-column&gt;
    &lt;p-column field="year" header="Year" sortable="custom" (sortFunction)="mysort($event)"&gt;&lt;/p-column&gt;
    &lt;p-column field="brand" header="Brand" sortable="true"&gt;&lt;/p-column&gt;
    &lt;p-column field="color" header="Color" sortable="true"&gt;&lt;/p-column&gt;
&lt;/p-dataTable&gt;
</code>
</pre>

<pre>
<code class="language-typescript" pCode ngNonBindable>
mysort(event) &#123;
    //event.field = Field to sort
    //event.order = Sort order
&#125;
</code>
</pre> 
            
            <p>See the <a [routerLink]="['/datatable/sort']">live example.</a></p>

            <h3>Filtering</h3>
            <p>Filtering is enabled by setting the filter property as true on a column. Default match mode is "startsWith" and this can be configured
            using filterMatchMode property that also accepts "contains", "endsWith", "equals" and "in".</p>
<pre>
<code class="language-markup" pCode ngNonBindable>
&lt;p-column field="vin" header="Vin (startsWith)" [filter]="true" filterPlaceholder="Search"&gt;&lt;/p-column&gt;
&lt;p-column field="year" header="Year (contains)" [filter]="true" filterMatchMode="contains"&gt;&lt;/p-column&gt;
&lt;p-column field="brand" header="Brand (startsWith)" [filter]="true"&gt;&lt;/p-column&gt;
&lt;p-column field="color" header="Color (endsWith)" [filter]="true" filterMatchMode="endsWith"&gt;&lt;/p-column&gt;
</code>
</pre>
            <p>An optional global filter feature is available to search all fields with the same keyword, to enable this place an input component whose keyup event would be 
            listened for filtering and bind the local ng-template variable name of it to the global filter property.</p>
<pre>
<code class="language-markup" pCode ngNonBindable>
&lt;input #gb type="text" placeholder="Global search"&gt;
&lt;p-dataTable [value]="cars" [rows]="10" [globalFilter]="gb"&gt;
</code>
</pre>

            <p>By default, input fields are used as filter elements and this can be customized using templating. It is important to use the on change callback 
                of the filter component to call the filter method of datatable by passing the value, field and matchmode properties.</p>
<pre>
<code class="language-markup" pCode ngNonBindable>
&lt;p-column field="brand" header="Brand (Custom)" [filter]="true" [style]="&#123;'overflow':'visible'&#125;" filterMatchMode="equals"&gt;
    &lt;ng-template pTemplate="filter" let-col&gt;
        &lt;p-dropdown [options]="brands" [style]="&#123;'width':'100%'&#125;" (onChange)="dt.filter($event.value,col.field,col.filterMatchMode)" styleClass="ui-column-filter"&gt;&lt;/p-dropdown&gt;
    &lt;/ng-template&gt;
&lt;/p-column&gt;
</code>
</pre>
        
            <p>See the <a [routerLink]="['/datatable/filter']">live example.</a></p>

            <h3>Selection</h3>
            <p>DataTable provides single and multiple selection modes on click of a row. Selected rows are bound to the selection property and onRowSelect-onRowUnselect events
            are provided as optional callbacks. Alternatively column based selection can be done using radio buttons or checkboxes using selectionMode of a particular column.</p>
            
            <p>In single mode, selection binding is an object reference.</p>
<pre>
<code class="language-typescript" pCode ngNonBindable>
export class DataTableDemo implements OnInit &#123;

    cars: Car[];
    
    selectedCar: Car;

    constructor(private carService: CarService) &#123; &#125;

    ngOnInit() &#123;
        this.carService.getCarsSmall().then(cars => this.cars = cars);
    &#125;
&#125;
</code>
</pre>

<pre>
<code class="language-markup" pCode ngNonBindable>
&lt;p-dataTable [value]="cars" selectionMode="single" [(selection)]="selectedCar" dataKey="vin"&gt;
    &lt;p-column field="vin" header="Vin"&gt;&lt;/p-column&gt;
    &lt;p-column field="year" header="Year"&gt;&lt;/p-column&gt;
    &lt;p-column field="brand" header="Brand"&gt;&lt;/p-column&gt;
    &lt;p-column field="color" header="Color"&gt;&lt;/p-column&gt;
&lt;/p-dataTable&gt;
</code>
</pre>

        <p>In multiple mode, selection binding should be an array and multiple items can either be selected
        using metaKey or toggled individually depending on the value of metaKeySelection property value which is true by default. On touch enabled
        devices metaKeySelection is turned off automatically.</p>
<pre>
<code class="language-typescript" pCode ngNonBindable>
export class DataTableDemo implements OnInit &#123;

    cars: Car[];
    
    selectedCars: Car[];

    constructor(private carService: CarService) &#123; &#125;

    ngOnInit() &#123;
        this.carService.getCarsSmall().then(cars => this.cars = cars);
    &#125;
&#125;
</code>
</pre>
<pre>
<code class="language-markup" pCode ngNonBindable>
&lt;p-dataTable [value]="cars" selectionMode="multiple" [(selection)]="selectedCars" dataKey="vin"&gt;
    &lt;p-column field="vin" header="Vin"&gt;&lt;/p-column&gt;
    &lt;p-column field="year" header="Year"&gt;&lt;/p-column&gt;
    &lt;p-column field="brand" header="Brand"&gt;&lt;/p-column&gt;
    &lt;p-column field="color" header="Color"&gt;&lt;/p-column&gt;
&lt;/p-dataTable&gt;
</code>
</pre>

            <p>If you prefer a radioButton or a checkbox instead of a row click, use the selectionMode of a column instead. Following datatable
            displays a checkbox at the first column of each row and automatically adds a header checkbox to toggle selection of all rows.</p>

<pre>
<code class="language-markup" pCode ngNonBindable>
&lt;p-dataTable [value]="cars" [(selection)]="selectedCars" dataKey="vin"&gt;
    &lt;p-column selectionMode="multiple"&gt;&lt;/p-column&gt;
    &lt;p-column field="vin" header="Vin"&gt;&lt;/p-column&gt;
    &lt;p-column field="year" header="Year"&gt;&lt;/p-column&gt;
    &lt;p-column field="brand" header="Brand"&gt;&lt;/p-column&gt;
    &lt;p-column field="color" header="Color"&gt;&lt;/p-column&gt;
&lt;/p-dataTable&gt;
</code>
</pre>

            <p>When resolving if a row is selected, by default DataTable compares selection array with the datasource which may cause a performance issue with huge datasets that do not use pagination.
                If available the fastest way is to use dataKey property that identifies a unique row so that DataTable can avoid comparing arrays as internally a map instance is used instead of looping arrays, on the other hand
                if dataKey cannot be provided consider using compareSelectionBy property as "equals" which uses reference comparison instead of the default "deepEquals" comparison. Latter is slower since it checks all properties.
                </p>

            <p>See the <a [routerLink]="['/datatable/selection']">live example.</a></p>

            <h3>ContextMenu</h3>
            <p>DataTable has exclusive integration with contextmenu component. In order to attach a menu to a datatable, define a local template
            variable for the menu and bind it to the contextMenu property of the datatable. This enables showing the menu whenever a row is right clicked.</p>
<pre>
<code class="language-markup" pCode ngNonBindable>
&lt;p-dataTable [value]="cars" selectionMode="single" [(selection)]="selectedCar" [contextMenu]="cm"&gt;
    &lt;p-header&gt;Right Click on Rows for ContextMenu&lt;/p-header&gt;
    &lt;p-column field="vin" header="Vin"&gt;&lt;/p-column&gt;
    &lt;p-column field="year" header="Year"&gt;&lt;/p-column&gt;
    &lt;p-column field="brand" header="Brand"&gt;&lt;/p-column&gt;
    &lt;p-column field="color" header="Color"&gt;&lt;/p-column&gt;
&lt;/p-dataTable&gt;

&lt;p-contextMenu #cm [model]="items"&gt;&lt;/p-contextMenu&gt;
</code>
</pre>

            <p>See the <a [routerLink]="['/datatable/contextmenu']">live example.</a></p>

            <h3>Editing</h3>
            <p>Incell editing is enabled by setting editable property true both on datatable and columns. Clicking a cell switches to edit mode
            and hitting enter key or clicking another cell switches it back to view mode.</p>
<pre>
<code class="language-markup" pCode ngNonBindable>
&lt;p-dataTable [value]="cars" [editable]="true"&gt;
    &lt;p-column field="vin" header="Vin" [editable]="true"&gt;&lt;/p-column&gt;
    &lt;p-column field="year" header="Year" [editable]="true"&gt;&lt;/p-column&gt;
    &lt;p-column field="brand" header="Brand" [editable]="true"&gt;&lt;/p-column&gt;
    &lt;p-column field="color" header="Color" [editable]="true"&gt;&lt;/p-column&gt;
&lt;/p-dataTable&gt;
</code>
</pre>

            <p>Simple input fields are used as the editor elements by default and this can be customized by adding a pTemplate named editor.</p>
<pre>
<code class="language-markup" pCode ngNonBindable>
&lt;p-dataTable [value]="cars" [editable]="true"&gt;
    &lt;p-column field="vin" header="Vin" [editable]="true"&gt;&lt;/p-column&gt;
    &lt;p-column field="year" header="Year" [editable]="true"&gt;&lt;/p-column&gt;
    &lt;p-column field="brand" header="Brand" [editable]="true" [style]="&#123;'overflow':'visible'&#125;"&gt;
        &lt;ng-template let-col let-car="rowData" pTemplate="editor"&gt;
            &lt;p-dropdown [(ngModel)]="car[col.field]" [options]="brands" [autoWidth]="false" [style]="&#123;'width':'100%'&#125;" required="true"&gt;&lt;/p-dropdown&gt;
        &lt;/ng-template&gt;
    &lt;/p-column&gt;
    &lt;p-column field="color" header="Color" [editable]="true"&gt;&lt;/p-column&gt;
    &lt;p-column field="saleDate" header="Sale Date" [editable]="true" [style]=" &#123;'overflow':'visible' &#125;"&gt;
        &lt;ng-template let-col let-car="rowData" pTemplate="body"&gt;
             &#123;&#123;car[col.field]|date &#125;&#125;
        &lt;/ng-template&gt;
        &lt;ng-template let-col let-car="rowData" pTemplate="editor"&gt;
            &lt;p-calendar [(ngModel)]="car[col.field]"&gt;&lt;/p-calendar&gt;
        &lt;/ng-template&gt;
    &lt;/p-column&gt;
&lt;/p-dataTable&gt;
</code>
</pre>

            <p>See the <a [routerLink]="['/datatable/editable']">live example.</a></p>

            <h3>Expandable Rows</h3>
            <p>Row expansion allows displaying detailed content for a particular row. To use this feature, enable expandableRows property, add an expander column and
            to declare the expanded content provide a pTemplate with "rowexpansion" as the value.</p>
<pre>
<code class="language-markup" pCode ngNonBindable>
&lt;p-dataTable [value]="cars" expandableRows="true"&gt;
    &lt;p-column expander="true" [style]="&#123;'width':'22px'&#125;"&gt;&lt;/p-column&gt;
    &lt;p-column field="vin" header="Vin"&gt;&lt;/p-column&gt;
    &lt;p-column field="year" header="Year"&gt;&lt;/p-column&gt;
    &lt;p-column field="brand" header="Brand"&gt;&lt;/p-column&gt;
    &lt;p-column field="color" header="Color"&gt;&lt;/p-column&gt;
    &lt;ng-template let-car pTemplate="rowexpansion"&gt;
        &lt;div class="ui-grid ui-grid-responsive ui-fluid" style="font-size:16px;padding:20px"&gt;
            &lt;div class="ui-grid-row"&gt;
                &lt;div class="ui-grid-col-3" style="text-align:center"&gt;
                    &lt;img src="assets/showcase/images/demo/car/{{car.brand}}.png"&gt;
                &lt;/div&gt;
                &lt;div class="ui-grid-col-9"&gt;
                    &lt;div class="ui-grid ui-grid-responsive ui-grid-pad"&gt;
                        &lt;div class="ui-grid-row"&gt;
                            &lt;div class="ui-grid-col-2 label"&gt;Vin: &lt;/div&gt;
                            &lt;div class="ui-grid-col-10"&gt;{{car.vin}}&lt;/div&gt;
                        &lt;/div&gt;
                        &lt;div class="ui-grid-row"&gt;
                            &lt;div class="ui-grid-col-2 label"&gt;Year: &lt;/div&gt;
                            &lt;div class="ui-grid-col-10"&gt;{{car.year}}&lt;/div&gt;
                        &lt;/div&gt;
                        &lt;div class="ui-grid-row"&gt;
                            &lt;div class="ui-grid-col-2 label"&gt;Brand: &lt;/div&gt;
                            &lt;div class="ui-grid-col-10"&gt;{{car.brand}}&lt;/div&gt;
                        &lt;/div&gt;
                        &lt;div class="ui-grid-row"&gt;
                            &lt;div class="ui-grid-col-2 label"&gt;Color: &lt;/div&gt;
                            &lt;div class="ui-grid-col-10"&gt;{{car.color}}&lt;/div&gt;
                        &lt;/div&gt;
                    &lt;/div&gt;
                &lt;/div&gt;
            &lt;/div&gt;
        &lt;/div&gt;
    &lt;/ng-template&gt;
&lt;/p-dataTable&gt;
</code>
</pre>
            <p>By default all rows are collapsed and expandedRows property needs to be populated 
                with the row data instances to show particular rows as expanded by default.</p>
            <p>See the <a [routerLink]="['/datatable/rowexpansion']">live example.</a></p>

            <h3>Column Resize</h3>
            <p>Columns can be resized using drag drop by setting the resizableColumns to true. There are two resize modes; "fit" and "expand". Fit is the default one and 
            the overall table width does not change when a column is resized. In "expand" mode, table width also changes along with the column width. onColumnResize
            is a callback that passes the resized column header as a parameter.</p>
            
<pre>
<code class="language-markup" pCode ngNonBindable>
&lt;p-dataTable [value]="cars" [resizableColumns]="true"&gt;
    &lt;p-column field="vin" header="Vin"&gt;&lt;/p-column&gt;
    &lt;p-column field="year" header="Year"&gt;&lt;/p-column&gt;
    &lt;p-column field="brand" header="Brand"&gt;&lt;/p-column&gt;
    &lt;p-column field="color" header="Color"&gt;&lt;/p-column&gt;
&lt;/p-dataTable&gt;
</code>
</pre>

            <p>It is important to note that when you need to change column widths, since table width is 100%, giving fixed pixel widths does not work well as browsers scale them, instead give percentage widths.</p>
<pre>
<code class="language-markup" pCode ngNonBindable>
&lt;p-dataTable [value]="cars" [resizableColumns]="true"&gt;
    &lt;p-column field="vin" header="Vin" [style]="&#123;'width':'20%'&#125;"&gt;&lt;/p-column&gt;
    &lt;p-column field="year" header="Year" [style]="&#123;'width':'30%'&#125;"&gt;&lt;/p-column&gt;
    &lt;p-column field="brand" header="Brand" [style]="&#123;'width':'15%'&#125;"&gt;&lt;/p-column&gt;
    &lt;p-column field="color" header="Color" [style]="&#123;'width':'35%'&#125;"&gt;&lt;/p-column&gt;
&lt;/p-dataTable&gt;
</code>
</pre>
            
            <p>See the <a [routerLink]="['/datatable/colresize']">live example.</a></p>

            <h3>Column Reordering</h3>
            <p>Columns can be reordered using drag drop by setting the reorderableColumns to true. onColReorder is a callback that is invoked when a column is reordered.</p>
<pre>
<code class="language-markup" pCode ngNonBindable>
&lt;p-dataTable [value]="cars" [reorderableColumns]="true"&gt;
    &lt;p-column field="vin" header="Vin"&gt;&lt;/p-column&gt;
    &lt;p-column field="year" header="Year"&gt;&lt;/p-column&gt;
    &lt;p-column field="brand" header="Brand"&gt;&lt;/p-column&gt;
    &lt;p-column field="color" header="Color"&gt;&lt;/p-column&gt;
&lt;/p-dataTable&gt;
</code>
</pre>
            <p>See the <a [routerLink]="['/datatable/colreorder']">live example.</a></p>
            
            <h3>Data Export</h3>
            <p>DataTable can export its data in CSV format using exportCSV() method.</p>
<pre>
<code class="language-markup" pCode ngNonBindable>
&lt;p-dataTable #dt [value]="cars"&gt;
    &lt;p-column field="vin" header="Vin"&gt;&lt;/p-column&gt;
    &lt;p-column field="year" header="Year"&gt;&lt;/p-column&gt;
    &lt;p-column field="brand" header="Brand"&gt;&lt;/p-column&gt;
    &lt;p-column field="color" header="Color"&gt;&lt;/p-column&gt;
&lt;/p-dataTable&gt; 

&lt;button type="button" pButton icon="fa-file-o" iconPos="left" label="CSV" (click)="dt.exportCSV()"&gt;&lt;/button&gt;
</code>
</pre>
            <p>See the <a [routerLink]="['/datatable/export']">live example.</a></p>

            <h3>Scrolling</h3>
            <p>DataTable supports both horizontal and vertical scrolling by defining scrollWidth and scrollHeight options respectively. The properties can take
            fixed pixels values or percentages to calculate scroll viewport relative to the parent of the datatable. Sample below uses vertical scrolling where
            headers are fixed and data is scrollable. In horizontal scrolling, it is important to give fixed widths to columns.</p>
<pre>
<code class="language-markup" pCode ngNonBindable>
&lt;p-dataTable [value]="cars" [scrollable]="true" scrollHeight="200px"&gt;
    &lt;p-column field="vin" header="Vin"&gt;&lt;/p-column&gt;
    &lt;p-column field="year" header="Year"&gt;&lt;/p-column&gt;
    &lt;p-column field="brand" header="Brand"&gt;&lt;/p-column&gt;
    &lt;p-column field="color" header="Color"&gt;&lt;/p-column&gt;
&lt;/p-dataTable&gt;
</code>
</pre>
            <p>In horizontal scrolling, certain columns can be fixed as well by enabling the frozen property at column level .</p>
<pre>
<code class="language-markup" pCode ngNonBindable>
&lt;p-dataTable [value]="cars" [scrollable]="true" scrollHeight="200px" frozenWidth="100px" scrollWidth="600px"&gt;
    &lt;p-column field="vin" header="Vin" frozen="true"&gt;&lt;/p-column&gt;
    &lt;p-column field="year" header="Year"&gt;&lt;/p-column&gt;
    &lt;p-column field="brand" header="Brand"&gt;&lt;/p-column&gt;
    &lt;p-column field="color" header="Color"&gt;&lt;/p-column&gt;
&lt;/p-dataTable&gt;
</code>
</pre>

            <p>In this case, if frozen and scrollable cells have content with varying height, misalignment might occur. To avoid a performance hit, DataTable avoid expensive calculations
                to align the row heights as it can be easily done with CSS manually.</p>
<pre>
<code class="language-markup" pCode ngNonBindable>
.ui-datatable .ui-datatable-frozen-view .ui-datatable-data > tr > td,
.ui-datatable .ui-datatable-unfrozen-view .ui-datatable-data > tr > td &#123;
    height: 24px;
&#125;
</code>
</pre>    

            <p>Additionally, virtualScroll mode enables dealing with large datasets by loading data on demand during scrolling.</p>

            <p>See the <a [routerLink]="['/datatable/scroll']">live example.</a></p>
            
            <h3>Lazy Loading</h3>
            <p>Lazy mode is handy to deal with large datasets, instead of loading the entire data, small chunks of data is loaded by invoking
             onLazyLoad callback everytime paging, sorting and filtering happens. To implement lazy loading,
            enable lazy attribute and provide a method callback using onLazyLoad that actually loads the data from a remote datasource. onLazyLoad gets an event object 
            that contains information about what to load. It is also important to assign the logical number of rows to totalRecords by doing a projection query for paginator configuration so that paginator 
            displays the UI assuming there are actually records of totalRecords size although in reality they aren't as in lazy mode, only the records that are displayed on the current page exist.</p>
<pre>
<code class="language-markup" pCode ngNonBindable>
&lt;p-dataTable [value]="cars" [scrollable]="true" [lazy]="true" (onLazyLoad)="loadData($event)" [totalRecords]="totalRecords"&gt;
    &lt;p-column field="vin" header="Vin"&gt;&lt;/p-column&gt;
    &lt;p-column field="year" header="Year"&gt;&lt;/p-column&gt;
    &lt;p-column field="brand" header="Brand"&gt;&lt;/p-column&gt;
    &lt;p-column field="color" header="Color"&gt;&lt;/p-column&gt;
&lt;/p-dataTable&gt;
</code>
</pre>
            
<pre>
<code class="language-typescript" pCode ngNonBindable>
loadData(event: LazyLoadEvent) &#123;
    //event.first = First row offset
    //event.rows = Number of rows per page
    //event.sortField = Field name to sort in single sort mode
    //event.sortOrder = Sort order as number, 1 for asc and -1 for dec in single sort mode
    //multiSortMeta: An array of SortMeta objects used in multiple columns sorting. Each SortMeta has field and order properties.
    //filters: Filters object having field as key and filter value, filter matchMode as value
    //globalFilter: Value of the global filter if available
    this.cars = //do a request to a remote datasource using a service and return the cars that match the lazy load criteria
&#125;
</code>
</pre>
            <p>See the <a [routerLink]="['/datatable/lazy']">live example.</a></p>

            <h3>Responsive</h3>
            <p>DataTable columns are displayed as stacked in responsive mode if the screen size becomes smaller than a certain breakpoint value. This feature is enabled
            by setting responsive to true.</p>
<pre>
<code class="language-markup" pCode ngNonBindable>
&lt;p-dataTable [value]="cars" [responsive]="true"&gt;
    &lt;p-column field="vin" header="Vin"&gt;&lt;/p-column&gt;
    &lt;p-column field="year" header="Year"&gt;&lt;/p-column&gt;
    &lt;p-column field="brand" header="Brand"&gt;&lt;/p-column&gt;
    &lt;p-column field="color" header="Color"&gt;&lt;/p-column&gt;
&lt;/p-dataTable&gt;
</code>
</pre>
            <p>See the <a [routerLink]="['/datatable/responsive']">live example.</a></p>
            
            <h3>Overlays in Cells</h3>
            <p>Cells of datatable hides the overflow by default, this prevents overlay of a component like dropdown to be displayed properly. In cases like these, 
            set the style of the column to allow overflow.</p>
<pre>
<code class="language-markup" pCode ngNonBindable>
&lt;p-column field="color" [style]="&#123;'overflow':'visible'&#125;"&gt;
    &lt;ng-template let-col let-car="rowData"&gt;
        &lt;p-dropdown&gt;&lt;/p-dropdown&gt;
    &lt;/ng-template&gt;
&lt;/p-column&gt;
</code>
</pre>
                
            <h3>Loading Status</h3>
            <p>DataTable has a loading property, when enabled a spinner icon is displayed to indicate data load.</p>
<pre>
<code class="language-markup" pCode ngNonBindable>
&lt;p-dataTable [value]="cars" [loading]="loading"&gt;
    &lt;p-column field="vin" header="Vin"&gt;&lt;/p-column&gt;
    &lt;p-column field="year" header="Year"&gt;&lt;/p-column&gt;
    &lt;p-column field="brand" header="Brand"&gt;&lt;/p-column&gt;
    &lt;p-column field="color" header="Color"&gt;&lt;/p-column&gt;
&lt;/p-dataTable&gt;
</code>
</pre>

<pre>
<code class="language-typescript" pCode ngNonBindable>
export class DataTableDemo implements OnInit &#123;

    loading: boolean;

    cars: Car[];

    constructor(private carService: CarService) &#123; &#125;

    ngOnInit() &#123;
        this.loading = true;
        setTimeout(() => &#123;
            this.carService.getCarsSmall().then(cars => this.cars = cars);
            this.loading = false;
        &#125;, 1000);
    &#125;
&#125;
</code>
</pre>

            <h3>Performance Tips Status</h3>
            <ul>
                <li>When selection is enabled use dataKey to avoid deep checking when comparing objects.</li>
                <li>Use rowTrackBy that internally uses ngForTrackBy to avoid unnecessary dom operations.</li>
                <li>Prefer lazy loading for large datasets.</li>
            </ul>

            <h3>Properties</h3>
            <div class="doc-tablewrapper">
                <table class="doc-table">
                    <thead>
                        <tr>
                            <th>Name</th>
                            <th>Type</th>
                            <th>Default</th>
                            <th>Description</th>
                        </tr>
                    </thead>
                    <tbody>
                        <tr>
                            <td>value</td>
                            <td>array</td>
                            <td>null</td>
                            <td>An array of objects to display.</td>
                        </tr>
                        <tr>
                            <td>headerRows</td>
                            <td>array</td>
                            <td>null</td>
                            <td>An array of column definitions for column grouping at header.</td>
                        </tr>
                        <tr>
                            <td>footerRows</td>
                            <td>array</td>
                            <td>null</td>
                            <td>An array of column definitions for column grouping at footer.</td>
                        </tr>
                        <tr>
                            <td>rows</td>
                            <td>number</td>
                            <td>null</td>
                            <td>Number of rows to display per page.</td>
                        </tr>
                        <tr>
                            <td>paginator</td>
                            <td>boolean</td>
                            <td>false</td>
                            <td>When specified as true, enables the pagination.</td>
                        </tr>
                        <tr>
                            <td>totalRecords</td>
                            <td>number</td>
                            <td>null</td>
                            <td>Number of total records, defaults to length of value when not defined.</td>
                        </tr>
                        <tr>
                            <td>pageLinks</td>
                            <td>number</td>
                            <td>null</td>
                            <td>Number of page links to display in paginator.</td>
                        </tr>
                        <tr>
                            <td>rowsPerPageOptions</td>
                            <td>array</td>
                            <td>null</td>
                            <td>Array of integer values to display inside rows per page dropdown of paginator</td>
                        </tr>
                        <tr>
                            <td>alwaysShowPaginator</td>
                            <td>boolean</td>
                            <td>true</td>
                            <td>Whether to show it even there is only one page.</td>
                        </tr>
                        <tr>
                            <td>sortMode</td>
                            <td>string</td>
                            <td>single</td>
                            <td>Defines whether sorting works on single column or on multiple columns.</td>
                        </tr>
                        <tr>
                            <td>sortField</td>
                            <td>string</td>
                            <td>null</td>
                            <td>Name of the field to sort data by default.</td>
                        </tr>
                        <tr>
                            <td>sortOrder</td>
                            <td>number</td>
                            <td>null</td>
                            <td>Order to sort the data by default.</td>
                        </tr>
                        <tr>
                            <td>multiSortMeta</td>
                            <td>array</td>
                            <td>null</td>
                            <td>An array of SortMeta objects to sort the data by default in multiple sort mode.</td>
                        </tr>
                        <tr>
                            <td>rowGroupMode</td>
                            <td>string</td>
                            <td>null</td>
                            <td>Type of the row grouping, valid values are "subheader" and "rowspan".</td>
                        </tr>
                        <tr>
                            <td>groupField</td>
                            <td>string</td>
                            <td>null</td>
                            <td>Name of the field to group by in subheader row grouping mode.</td>
                        </tr>
                        <tr>
                            <td>sortableGroupRow</td>
                            <td>boolean</td>
                            <td>true</td>
                            <td>Whether to sort the data if the row group subheader is clicked.</td>
                        </tr>
                        <tr>
                            <td>expandableRowGroups</td>
                            <td>boolean</td>
                            <td>false</td>
                            <td>When enabled, adds a clickable icon at group header to expand or collapse the group.</td>
                        </tr>
                        <tr>
                            <td>expandedRowGroups</td>
                            <td>array</td>
                            <td>null</td>
                            <td>Collection of group field values to show a group as expanded by default.</td>
                        </tr>
                        <tr>
                            <td>responsive</td>
                            <td>boolean</td>
                            <td>false</td>
                            <td>Defines if the columns should be stacked in smaller screens.</td>
                        </tr>
                        <tr>
                            <td>selectionMode</td>
                            <td>string</td>
                            <td>null</td>
                            <td>Specifies the selection mode, valid values are "single" and "multiple".</td>
                        </tr>                        
                        <tr>
                            <td>headerCheckboxToggleAllPages</td>
                            <td>boolean</td>
                            <td>false</td>
                            <td>
                                When set to true, the header checkbox on paged DataTables with checkbox multiple 
                                selection enabled will toggle the selection of items across all pages. See the
                                <a [routerLink]="['/datatable/selection']">live example.</a>
                            </td>
                        </tr>
                        <tr>
                            <td>selection</td>
                            <td>any</td>
                            <td>null</td>
                            <td>Selected row in single mode or an array of values in multiple mode.</td>
                        </tr>
                        <tr>
                            <td>editable</td>
                            <td>boolean</td>
                            <td>false</td>
                            <td>Activates incell editing when enabled.</td>
                        </tr>
                        <tr>
                            <td>expandableRows</td>
                            <td>boolean</td>
                            <td>false</td>
                            <td>Activates expandable rows feature when true.</td>
                        </tr>
                        <tr>
                            <td>expandedRows</td>
                            <td>array</td>
                            <td>null</td>
                            <td>Collection of rows to display as expanded.</td>
                        </tr>
                        <tr>
                            <td>rowExpandMode</td>
                            <td>string</td>
                            <td>multiple</td>
                            <td>Whether multiple rows can be expanded at any time. Valid values are "multiple" and "single".</td>
                        </tr>
                        <tr>
                            <td>globalFilter</td>
                            <td>any</td>
                            <td>null</td>
                            <td>Reference of an input field to use as a global filter.</td>
                        </tr>
                        <tr>
                            <td>filterDelay</td>
                            <td>number</td>
                            <td>300</td>
                            <td>Delay in milliseconds before filtering the data.</td>
                        </tr>
                        <tr>
                            <td>lazy</td>
                            <td>boolean</td>
                            <td>false</td>
                            <td>Defines if data is loaded and interacted with in lazy manner.</td>
                        </tr>
                        <tr>
                            <td>resizableColumns</td>
                            <td>boolean</td>
                            <td>false</td>
                            <td>When enabled, columns can be resized using drag and drop.</td>
                        </tr>
                        <tr>
                            <td>columnResizeMode</td>
                            <td>string</td>
                            <td>fit</td>
                            <td>Defines whether the overall table width should change on column resize, valid values are "fit" and "expand".</td>
                        </tr>
                        <tr>
                            <td>reorderableColumns</td>
                            <td>boolean</td>
                            <td>false</td>
                            <td>When enabled, columns can be reordered using drag and drop.</td>
                        </tr>
                        <tr>
                            <td>scrollable</td>
                            <td>boolean</td>
                            <td>false</td>
                            <td>When specifies, enables horizontal and/or vertical scrolling.</td>
                        </tr>
                        <tr>
                            <td>scrollHeight</td>
                            <td>number/string</td>
                            <td>null</td>
                            <td>Height of the scroll viewport, can be pixel as a number or a percentage.</td>
                        </tr>
                        <tr>
                            <td>scrollWidth</td>
                            <td>number/string</td>
                            <td>null</td>
                            <td>Width of the scroll viewport, can be pixel as a number or a percentage.</td>
                        </tr>
                        <tr>
                            <td>virtualScroll</td>
                            <td>boolean</td>
                            <td>false</td>
                            <td>Whether the data should be loaded on demand during scroll.</td>
                        </tr>
                        <tr>
                            <td>style</td>
                            <td>string</td>
                            <td>null</td>
                            <td>Inline style of the component.</td>
                        </tr>
                        <tr>
                            <td>styleClass</td>
                            <td>string</td>
                            <td>null</td>
                            <td>Style class of the component.</td>
                        </tr>
                        <tr>
                            <td>contextMenu</td>
                            <td>ContextMenu</td>
                            <td>null</td>
                            <td>Local ng-template varilable of a ContextMenu.</td>
                        </tr>
                        <tr>
                            <td>csvSeparator</td>
                            <td>string</td>
                            <td>,</td>
                            <td>Character to use as the csv separator.</td>
                        </tr>
                        <tr>
                            <td>exportFilename</td>
                            <td>string</td>
                            <td>download</td>
                            <td>Name of the exported file.</td>
                        </tr>
                        <tr>
                            <td>emptyMessage</td>
                            <td>string</td>
                            <td>No records found.</td>
                            <td>Text to display when there is no data.</td>
                        </tr>
                        <tr>
                            <td>paginatorPosition</td>
                            <td>string</td>
                            <td>bottom</td>
                            <td>Position of the paginator, options are "top","bottom" or "both".</td>
                        </tr>
                        <tr>
                            <td>rowStyleClass</td>
                            <td>function</td>
                            <td>null</td>
                            <td>Function that gets the row data and row index as parameters and returns a style class for the row.</td>
                        </tr>
                        <tr>
                            <td>rowHover</td>
                            <td>boolean</td>
                            <td>false</td>
                            <td>Adds hover effect to rows without the need for selectionMode.</td>
                        </tr>
                        <tr>
                            <td>filters</td>
                            <td>array</td>
                            <td>null</td>
                            <td>An array of FilterMetadata objects to provide external filters.</td>
                        </tr>
                        <tr>
                            <td>metaKeySelection</td>
                            <td>boolean</td>
                            <td>true</td>
                            <td>Defines whether metaKey is requred or not for the selection. When true metaKey needs to be pressed to select or unselect an item and when set to false selection of each item
                            can be toggled individually. On touch enabled devices, metaKeySelection is turned off automatically.</td>
                        </tr>
                        <tr>
                            <td>dataKey</td>
                            <td>string</td>
                            <td>null</td>
                            <td>A property to uniquely identify a record in data.</td>
                        </tr>
                        <tr>
                            <td>loading</td>
                            <td>boolean</td>
                            <td>false</td>
                            <td>Displays a loader to indicate data load is in progress.</td>
                        </tr>
                        <tr>
                            <td>rowTrackBy</td>
                            <td>Function</td>
                            <td>null</td>
                            <td>Function to optimize the dom operations by delegating to ngForTrackBy, default algoritm checks for object identity.</td>
                        </tr>
                        <tr>
                            <td>compareSelectionBy</td>
                            <td>string</td>
                            <td>deepEquals</td>
                            <td>Algorithm to define if a row is selected, valid values are "equals" that compares by reference and "deepEquals" that compares all fields.</td>
                        </tr>
                        <tr>
                            <td>first</td>
                            <td>number</td>
                            <td>0</td>
                            <td>Index of the first row to be displayed. It supports two-way binding so that model value can be updated on pagination as well.</td>
                        </tr>
                    </tbody>
                </table>
            </div>

            <h3>Events</h3>
            <div class="doc-tablewrapper">
                <table class="doc-table">
                    <thead>
                    <tr>
                        <th>Name</th>
                        <th>Parameters</th>
                        <th>Description</th>
                    </tr>
                    </thead>
                    <tbody>
                        <tr>
                            <td>onRowClick</td>
                            <td>event.originalEvent: Browser event <br>
                                event.data: Selected data </td>
                            <td>Callback to invoke when a row is clicked.</td>
                        </tr>
                        <tr>
                            <td>onRowSelect</td>
                            <td>event.originalEvent: Browser event <br>
                                event.data: Selected data <br >
                                event.type: Type of selection, valid values are "row", "radiobutton" and "checkbox"
                            </td>
                            <td>Callback to invoke when a row is selected.</td>
                        </tr>
                        <tr>
                            <td>onRowUnselect</td>
                            <td>event.originalEvent: Browser event <br>
                                event.data: Unselected data <br >
                                event.type: Type of unselection, valid values are "row" and "checkbox"</td>
                            <td>Callback to invoke when a row is unselected with metakey.</td>
                        </tr>
                        <tr>
                            <td>onRowDblclick</td>
                            <td>event.originalEvent: Browser event <br>
                                event.data: Selected data </td>
                            <td>Callback to invoke when a row is selected with double clicked.</td>
                        </tr>
                        <tr>
                            <td>onHeaderCheckboxToggle</td>
                            <td>event.originalEvent: Browser event <br>
                                event.checked: State of the header checkbox</td>
                            <td>Callback to invoke when state of header checkbox changes.</td>
                        </tr>
                        <tr>
                            <td>onContextMenuSelect</td>
                            <td>event.originalEvent: Browser event <br>
                                event.data: Selected data</td>
                            <td>Callback to invoke when a row is selected with right click.</td>
                        </tr>
                        <tr>
                            <td>onColResize</td>
                            <td>event.element: Resized column header <br>
                                event.delta: Change of width in number of pixels</td>
                            <td>Callback to invoke when a column is resized.</td>
                        </tr>
                        <tr>
                            <td>onColReorder</td>
                            <td>event.dragIndex: Index of the dragged column <br>
                                event.dropIndex: Index of the dropped column <br>
                                event.columns: Columns array after reorder. <br></td>
                            <td>Callback to invoke when a column is reordered.</td>
                        </tr>
                        <tr>
                            <td>onLazyLoad</td>
                            <td>event.first = First row offset <br>
                                event.rows = Number of rows per page <br>
                                event.sortField = Field name to sort with <br>
                                event.sortOrder = Sort order as number, 1 for asc and -1 for dec <br>
                                filters: FilterMetadata object having field as key and filter value, filter matchMode as value</td>
                            <td>Callback to invoke when paging, sorting or filtering happens in lazy mode.</td>
                        </tr>
                        <tr>
                            <td>onEditInit</td>
                            <td>event.column: Column object of the cell<br>
                                event.data: Row data</td>
                            <td>Callback to invoke when a cell switches to edit mode.</td>
                        </tr>
                        <tr>
                            <td>onEdit</td>
                            <td>event.originalEvent: Browser event
                                event.column: Column object of the cell<br>
                                event.data: Row data <br />
                                event.index: Row index</td>
                            <td>Callback to invoke when cell data is being edited.</td>
                        </tr>
                        <tr>
                            <td>onEditComplete</td>
                            <td>event.column: Column object of the cell<br>
                                event.data: Row data <br />
                                event.index: Row index</td>
                            <td>Callback to invoke when cell edit is completed.</td>
                        </tr>
                        <tr>
                            <td>onEditCancel</td>
                            <td>event.column: Column object of the cell<br>
                                event.data: Row data <br />
                                event.index: Row index</td>
                            <td>Callback to invoke when cell edit is cancelled with escape key.</td>
                        </tr>
                        <tr>
                            <td>onPage</td>
                            <td>event.first: Index of first record in page<br>
                                event.rows: Number of rows on the page</td>
                            <td>Callback to invoke when pagination occurs.</td>
                        </tr>
                        <tr>
                            <td>onSort</td>
                            <td>event.field: Field name of the sorted column<br>
                                event.order: Sort order as 1 or -1<br>
                                event.multisortmeta: Sort metadata in multi sort mode. See multiple sorting section for the structure of this object.</td>
                            <td>Callback to invoke when a column gets sorted.</td>
                        </tr>
                        <tr>
                            <td>onFilter</td>
                            <td>event.filters: Filters object having a field as the property key and an object with value, matchMode as the property value.<br>
                                event.filteredValue: Filtered data after running the filtering.</td>
                            <td>Callback to invoke when data is filtered.</td>
                        </tr>
                        <tr>
                            <td>onRowExpand</td>
                            <td>event.originalEvent: Browser event<br>
                                data: Row data to expand.</td>
                            <td>Callback to invoke when a row is expanded.</td>
                        </tr>
                        <tr>
                            <td>onRowCollapse</td>
                            <td>event.originalEvent: Browser event<br>
                                data: Row data to collapse.</td>
                            <td>Callback to invoke when a row is collapsed.</td>
                        </tr>
                        <tr>
                            <td>onRowGroupExpand</td>
                            <td>event.originalEvent: Browser event<br>
                                group: Value of the group.</td>
                            <td>Callback to invoke when a row group is expanded.</td>
                        </tr>
                        <tr>
                            <td>onRowGroupCollapse</td>
                            <td>event.originalEvent: Browser event<br>
                                group: Value of the group.</td>
                            <td>Callback to invoke when a row group is collapsed.</td>
                        </tr>
                    </tbody>
                </table>
            </div>

<pre>
<code class="language-markup" pCode ngNonBindable>
&lt;p-dataTable [value]="cars" selectionMode="single" [(selection)]="selectedCar" (onRowSelect)="handleRowSelect($event)"&gt;
    &lt;p-column field="vin" header="Vin"&gt;&lt;/p-column&gt;
    &lt;p-column field="year" header="Year"&gt;&lt;/p-column&gt;
    &lt;p-column field="brand" header="Brand"&gt;&lt;/p-column&gt;
    &lt;p-column field="color" header="Color"&gt;&lt;/p-column&gt;
&lt;/p-dataTable&gt;
</code>
</pre>

<pre>
<code class="language-typescript" pCode ngNonBindable>
handleRowSelect(event) &#123;
    //event.data = Selected row data
&#125;
</code>
</pre>

            <h3>Methods</h3>
            <div class="doc-tablewrapper">
                <table class="doc-table">
                    <thead>
                        <tr>
                            <th>Name</th>
                            <th>Parameters</th>
                            <th>Description</th>
                        </tr>
                    </thead>
                    <tbody>
                        <tr>
                            <td>reset</td>
                            <td>-</td>
                            <td>Resets sort, filter and paginator state.</td>
                        </tr>
                        <tr>
                            <td>exportCSV</td>
                            <td>-</td>
                            <td>Exports the data in csv format.</td>
                        </tr>
                        <tr>
                            <td>toggleRow</td>
                            <td>data</td>
                            <td>Toggles row expansion for given row data.</td>
                        </tr>
                    </tbody>
                </table>
            </div>
            
<pre>
<code #dt class="language-markup" pCode ngNonBindable>
&lt;p-dataTable #dt [value]="cars"&gt;
    &lt;p-column field="vin" header="Vin"&gt;&lt;/p-column&gt;
    &lt;p-column field="year" header="Year"&gt;&lt;/p-column&gt;
    &lt;p-column field="brand" header="Brand"&gt;&lt;/p-column&gt;
    &lt;p-column field="color" header="Color"&gt;&lt;/p-column&gt;
&lt;/p-dataTable&gt;

&lt;button type="button" pButton (click)="update(dt)" label="Reset"&gt;&lt;/button&gt;
</code>
</pre>

<pre>
<code class="language-typescript" pCode ngNonBindable>
update(dt: DataTable) &#123;
    dt.reset();
&#125;
</code>
</pre>

            <h3>Styling</h3>
            <p>Following is the list of structural style classes, for theming classes visit <a href="#" [routerLink]="['/theming']">theming page</a>.</p>
            <div class="doc-tablewrapper">
                <table class="doc-table">
                    <thead>
                    <tr>
                        <th>Name</th>
                        <th>Element</th>
                    </tr>
                    </thead>
                    <tbody>
                        <tr>
                            <td>ui-datatable</td>
                            <td>Container element.</td>
                        </tr>
                        <tr>
                            <td>ui-datatable-header</td>
                            <td>Header section.</td>
                        </tr>
                        <tr>
                            <td>ui-datatable-footer</td>
                            <td>Footer section.</td>
                        </tr>
                        <tr>
                            <td>ui-column-title</td>
                            <td>Title of a column.</td>
                        </tr>
                        <tr>
                            <td>ui-sortable-column</td>
                            <td>Sortable column header.</td>
                        </tr>
                        <tr>
                            <td>ui-column-filter</td>
                            <td>Filter element in header.</td>
                        </tr>
                        <tr>
                            <td>ui-cell-data</td>
                            <td>Data cell in body.</td>
                        </tr>
                        <tr>
                            <td>ui-cell-editor</td>
                            <td>Input element for incell editing.</td>
                        </tr>
                        <tr>
                            <td>ui-datatable-scrollable-header</td>
                            <td>Container of header in a scrollable table.</td>
                        </tr>
                        <tr>
                            <td>ui-datatable-scrollable-header</td>
                            <td>Container of body in a scrollable table.</td>
                        </tr>
                        <tr>
                            <td>ui-datatable-scrollable-header</td>
                            <td>Container of footer in a scrollable table.</td>
                        </tr>
                        <tr>
                            <td>ui-datatable-responsive</td>
                            <td>Container element of a responsive datatable.</td>
                        </tr>
                        <tr>
                            <td>ui-datatable-emptymessage</td>
                            <td>Cell containing the empty message.</td>
                        </tr>
                    </tbody>
                </table>
            </div>

            <h3>Dependencies</h3>
            <p>None.</p>
        </p-tabPanel>

        <p-tabPanel header="Source">
            <a href="https://github.com/primefaces/primeng/tree/master/src/app/showcase/components/datatable" class="btn-viewsource" target="_blank">
                <i class="fa fa-github"></i>
                <span>View on GitHub</span>
            </a>
<pre>
<code class="language-markup" pCode ngNonBindable>
&lt;h3 class="first"&gt;Basic&lt;/h3&gt;
&lt;p-dataTable [value]="cars"&gt;
    &lt;p-column field="vin" header="Vin"&gt;&lt;/p-column&gt;
    &lt;p-column field="year" header="Year"&gt;&lt;/p-column&gt;
    &lt;p-column field="brand" header="Brand"&gt;&lt;/p-column&gt;
    &lt;p-column field="color" header="Color"&gt;&lt;/p-column&gt;
&lt;/p-dataTable&gt;

&lt;h3&gt;Dynamic Columns&lt;/h3&gt;
&lt;p-dataTable [value]="cars"&gt;
    &lt;p-column *ngFor="let col of cols" [field]="col.field" [header]="col.header"&gt;&lt;/p-column&gt;
&lt;/p-dataTable&gt;
</code>
</pre>

<pre>
<code class="language-typescript" pCode ngNonBindable>
export class DataTableDemo implements OnInit &#123;

    cars: Car[];
    
    cols: any[];
    
    constructor(private carService: CarService) &#123; &#125;

    ngOnInit() &#123;
        this.carService.getCarsSmall().then(cars => this.cars = cars);
        
        this.cols = [
            &#123;field: 'vin', header: 'Vin'&#125;,
            &#123;field: 'year', header: 'Year'&#125;,
            &#123;field: 'brand', header: 'Brand'&#125;,
            &#123;field: 'color', header: 'Color'&#125;
        ];
    &#125;
&#125;
</code>
</pre>


        </p-tabPanel>
    </p-tabView>
</div>
